// OpentTxl-C Version 11 safe C try/catch exception handling
// Copyright 2023, James R. Cordy and others

// Safe C try/catch exception handling 

// Example:
//      try {
//          ...
//          throw (99);
//          ...
//      } catch {
//          if (exception = 99) {
//              fprintf (stderr, "caught signal %d\n", exception);
//          }
//          throw (1);
//      }

// Standard signal handling library
#include <setjmp.h>

struct trycatch_handlerT {
    int code;
    jmp_buf environment;
    struct trycatch_handlerT *prevhandler;
}; 

extern struct trycatch_handlerT *trycatch_activehandler;
extern struct trycatch_handlerT *trycatch_currenthandler;
extern struct trycatch_handlerT trycatch_defaulthandler;

#define trycatch_enterhandler(handler)  \
        ( \
            handler.prevhandler = trycatch_activehandler, \
            trycatch_activehandler = &handler, \
            trycatch_activehandler->code = 0, \
            setjmp (trycatch_activehandler->environment) \
        )

#define trycatch_exithandler()  \
        { \
            trycatch_activehandler = trycatch_activehandler->prevhandler; \
        }

#define trycatch_throwhandler(throwcode)  \
        { \
            trycatch_currenthandler = trycatch_activehandler; \
            trycatch_currenthandler->code = throwcode; \
            if (trycatch_currenthandler != &trycatch_defaulthandler) \
                trycatch_activehandler = trycatch_activehandler->prevhandler; \
            longjmp (trycatch_currenthandler->environment, throwcode); \
        }

#define try                     struct trycatch_handlerT trycatch_handler; if (!(trycatch_enterhandler (trycatch_handler))) {
#define catch                   trycatch_exithandler(); } else 
#define throw(code)             trycatch_throwhandler(code)
#define exception               trycatch_handler.code

#ifdef MAIN
extern void tcinitialize (int argc, char **argv);
extern void tcfinalize (void);
#endif

// Disable unsafe C setjmp/longjmp signal handling 
// ***NO***! macros above use it!
// #undef setjmp
// #undef sigsetjmp
// #undef longjmp
// #undef siglongjmp
